package com.example.demo.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.demo.dao.ProductBaseAddonRelationMapper;
import com.example.demo.dao.ProductMapper;
import com.example.demo.dao.ProductSkuMapper;
import com.example.demo.dao.ProductSpecOptionMapper;
import com.example.demo.dao.ProductSpecValueMapper;
import com.example.demo.dao.ProductStatusMapper;
import com.example.demo.dao.ShopMapper;
import com.example.demo.dao.ShoppingCartAddonRelationMapper;
import com.example.demo.dao.ShoppingCartMapper;
import com.example.demo.domain.app.param.ShoppingCartParam;
import com.example.demo.domain.app.param.ShoppingCartSelectParam;
import com.example.demo.domain.app.param.ShoppingCartUpdateNumParam;
import com.example.demo.domain.app.vo.GoodsStatusVO;
import com.example.demo.domain.app.vo.ProductAdditionVO;
import com.example.demo.domain.app.vo.ProductSkuVO;
import com.example.demo.domain.app.vo.ShopVO;
import com.example.demo.domain.app.vo.ShoppingCartItemVO;
import com.example.demo.domain.app.vo.ShoppingCartVO;
import com.example.demo.domain.entity.ProductBaseAddonRelationDO;
import com.example.demo.domain.entity.ProductDO;
import com.example.demo.domain.entity.ProductSkuDO;
import com.example.demo.domain.entity.ProductSpecOptionDO;
import com.example.demo.domain.entity.ProductSpecValueDO;
import com.example.demo.domain.entity.ProductStatusDO;
import com.example.demo.domain.entity.ShopDO;
import com.example.demo.domain.entity.ShoppingCartAddonRelationDO;
import com.example.demo.domain.entity.ShoppingCartDO;
import com.example.demo.exception.BizException;
import com.example.demo.exception.ErrorConstants;
import com.example.demo.service.ShoppingCartService;
import com.example.demo.util.SpecJsonUtils;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * ShoppingCartServiceImpl
 *
 * @author haochen78
 * @date 2025/11/9 16:03
 **/
@Service
public class ShoppingCartServiceImpl implements ShoppingCartService {

    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ProductStatusMapper productStatusMapper;
    @Autowired
    private ShopMapper shopMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private ProductSkuMapper productSkuMapper;
    @Autowired
    private ProductBaseAddonRelationMapper productBaseAddonRelationMapper;
    @Autowired
    private ShoppingCartAddonRelationMapper shoppingCartAddonRelationMapper;
    @Autowired
    private ProductSpecOptionMapper productSpecOptionMapper;
    @Autowired
    private ProductSpecValueMapper productSpecValueMapper;

    @Override
    public ShoppingCartVO info() {
        Long userId = StpUtil.getLoginIdAsLong();

        ShoppingCartVO result = new ShoppingCartVO();

        // 查询所有未删除的购物车主记录
        LambdaQueryWrapper<ShoppingCartDO> cartWrapper = new LambdaQueryWrapper<>();
        cartWrapper.eq(ShoppingCartDO::getUserId, userId);
        List<ShoppingCartDO> carts = shoppingCartMapper.selectList(cartWrapper);

        if (CollectionUtils.isEmpty(carts)) {
            result.setItems(Collections.emptyList());
            result.setShopList(Collections.emptySet());
            result.setGoodsStatus(Collections.emptyList());
            result.setNumber(0);
            result.setPrice(BigDecimal.ZERO);
            result.setScore(0);
            return result;
        }

        Set<Long> productIds = carts.stream().map(ShoppingCartDO::getProductId).collect(Collectors.toSet());
        Set<Long> skuIds = carts.stream().map(ShoppingCartDO::getSkuId).collect(Collectors.toSet());
        Set<Long> cartIds = carts.stream().map(ShoppingCartDO::getId).collect(Collectors.toSet());
        Set<Long> shopIds = carts.stream().map(ShoppingCartDO::getShopId).collect(Collectors.toSet());

        // 批量查询商品 k:商品id
        Map<Long, ProductDO> productMap = productMapper.selectBatchIds(productIds).stream().collect(Collectors.toMap(ProductDO::getId, p -> p));
        // 批量查询商品状态 k:商品id
        LambdaQueryWrapper<ProductStatusDO> statusWrapper = new LambdaQueryWrapper<>();
        statusWrapper.in(ProductStatusDO::getProductId, productIds);
        List<ProductStatusDO> statusList = productStatusMapper.selectList(statusWrapper);
        Map<Long, ProductStatusDO> productStatusMap = statusList.stream().collect(Collectors.toMap(ProductStatusDO::getProductId, Function.identity(), (s1, s2) -> s1));
        // 批量查询商品规格 k:规格id
        Map<Long, ProductSkuDO> skuMap = productSkuMapper.selectBatchIds(skuIds).stream().collect(Collectors.toMap(ProductSkuDO::getId, s -> s));
        // 批量查询商品附加项 K:购物车id
        Map<Long, List<ShoppingCartAddonRelationDO>> addonMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(cartIds)) {
            LambdaQueryWrapper<ShoppingCartAddonRelationDO> addonWrapper = new LambdaQueryWrapper<>();
            addonWrapper.in(ShoppingCartAddonRelationDO::getCartId, cartIds);
            List<ShoppingCartAddonRelationDO> addons = shoppingCartAddonRelationMapper.selectList(addonWrapper);
            addonMap = addons.stream().collect(Collectors.groupingBy(ShoppingCartAddonRelationDO::getCartId));
        }
        // 批量查询商铺 k:商店id
        Map<Long, ShopDO> shopMap = shopMapper.selectBatchIds(shopIds).stream().collect(Collectors.toMap(ShopDO::getId, Function.identity(), (s1, s2) -> s1));

        // 构造购物车 items
        List<ShoppingCartItemVO> items = new ArrayList<>();
        int totalNumber = 0;
        BigDecimal totalPrice = BigDecimal.ZERO;
        int totalScore = 0;

        Set<ShopVO> shopSet = Sets.newHashSet();
        for (ShoppingCartDO cart : carts) {
            ProductDO product = productMap.get(cart.getProductId());
            ProductSkuDO sku = skuMap.get(cart.getSkuId());
            ProductStatusDO productStatus = productStatusMap.get(cart.getProductId());
            if (product == null || sku == null) {
                continue;
            }

            ShoppingCartItemVO item = new ShoppingCartItemVO();
            item.setKey(cart.getId());
            item.setShopId(product.getShopId());
            item.setGoodsId(product.getId());
            item.setCategoryId(product.getCategoryId());
            item.setName(product.getName());
            item.setPic(product.getPic());
            item.setNumber(cart.getQuantity());
            item.setPrice(sku.getSalePrice());
            item.setStores(sku.getStockQuantity());
            item.setSelected(cart.getIsSelected() == 1);
            item.setStatus(productStatus.getStatus());
            item.setStatusStr(productStatus.getStatusStr());

            // SKU 规格
            if (StringUtils.isNotBlank(sku.getSpecJson())) {
                Map<Long, Long> specMap = SpecJsonUtils.stringToMap(sku.getSpecJson());
                Set<Long> optionIds = specMap.keySet();
                Collection<Long> valueIds = specMap.values();

                List<ProductSpecOptionDO> options = productSpecOptionMapper.selectBatchIds(optionIds);
                List<ProductSpecValueDO> values = productSpecValueMapper.selectBatchIds(valueIds);
                Map<Long, String> optionIdToName = options.stream().collect(Collectors.toMap(ProductSpecOptionDO::getId, ProductSpecOptionDO::getName));
                Map<Long, String> valueIdToEntity = values.stream().collect(Collectors.toMap(ProductSpecValueDO::getId, ProductSpecValueDO::getName));

                List<ProductSkuVO> skuVOList = specMap.entrySet().stream().map(m -> {
                    Long optionId = m.getKey();
                    Long valueId = m.getValue();

                    ProductSkuVO vo = new ProductSkuVO();
                    vo.setOptionId(optionId);
                    vo.setOptionName(optionIdToName.getOrDefault(optionId, "未知规格项"));
                    vo.setOptionValueId(valueId);
                    vo.setOptionValueName(valueIdToEntity.getOrDefault(valueId, "未知规格值"));
                    return vo;
                }).collect(Collectors.toList());
                item.setSku(skuVOList);
            }

            // 附加项
            List<ShoppingCartAddonRelationDO> addons = addonMap.get(cart.getId());
            if (CollectionUtils.isNotEmpty(addons)) {
                List<ProductAdditionVO> additionVos = addons.stream().map(addon -> {
                    ProductAdditionVO vo = new ProductAdditionVO();
                    vo.setId(addon.getAddonValueId());     // valueId
                    vo.setPid(addon.getAddonOptionId());     // optionId
                    vo.setName(addon.getAddonValueName());
                    vo.setPname(addon.getAddonOptionName());
                    vo.setPrice(addon.getAddonPrice());
                    return vo;
                }).collect(Collectors.toList());
                item.setAdditions(additionVos);
            }

            items.add(item);

            // 4. 查询店铺信息
            ShopDO shop = shopMap.get(cart.getShopId());
            ShopVO shopVO = new ShopVO();
            shopVO.setId(shop.getId());
            shopVO.setName(shop.getName());
            shopVO.setPic(shop.getLogo());
            shopVO.setLatitude(shop.getLatitude());
            shopVO.setLongitude(shop.getLongitude());
            shopVO.setServiceDistance(shop.getServiceDistance());
            shopSet.add(shopVO);

            if (cart.getIsSelected() != 1) {
                continue;
            }
            // 统计
            totalNumber += cart.getQuantity();
            totalPrice = totalPrice.add(sku.getSalePrice().multiply(BigDecimal.valueOf(cart.getQuantity())));
            // score 暂按商品积分计算（假设 product 有 score 字段）
            //totalScore += (product.getShopId() == null ? 0 : product.getScore()) * cart.getNumber();

        }

        result.setShopList(shopSet);

        // 5. 商品状态快照（简化版：直接用商品当前状态）
        List<GoodsStatusVO> goodsStatus = productIds.stream().map(id -> {
            ProductDO p = productMap.get(id);
            GoodsStatusVO gs = new GoodsStatusVO();
            gs.setId(id);
            //gs.setSellEnd(p.getSaleEndTime() != null && System.currentTimeMillis() > p.getSaleEndTime().getTime());
            //gs.setSellStart(p.getSaleStartTime() == null || System.currentTimeMillis() >= p.getSaleStartTime().getTime());
            ProductStatusDO productStatusDO = productStatusMap.get(id);
            if (Objects.nonNull(productStatusDO)) {
                gs.setStatus(productStatusDO.getStatus());
                gs.setStatusStr(productStatusDO.getStatusStr());
            }
            gs.setStores(skuMap.values().stream().filter(s -> Objects.equals(s.getProductId(), id)).mapToInt(ProductSkuDO::getStockQuantity).sum());
            return gs;
        }).collect(Collectors.toList());
        result.setGoodsStatus(goodsStatus);

        // 6. 设置汇总
        result.setItems(items);
        result.setNumber(totalNumber);
        result.setPrice(totalPrice);
        result.setScore(totalScore);

        return result;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ShoppingCartVO add(ShoppingCartParam param) {
        Long currentUserId = StpUtil.getLoginIdAsLong();

        // 1. 校验商品
        ProductDO productDO = productMapper.selectById(param.getGoodsId());
        if (Objects.isNull(productDO)) {
            throw new BizException(ErrorConstants.SERVER_INTERNAL_ERROR, "商品不存在");
        }

        // 2. 校验 SKU
        String specJson = null;
        if (CollectionUtils.isNotEmpty(param.getSku())) {
            Map<Long, Long> skuMap = param.getSku().stream().collect(Collectors.toMap(ShoppingCartParam.ProductSku::getOptionId, ShoppingCartParam.ProductSku::getOptionValueId, (x, y) -> x));
            specJson = SpecJsonUtils.mapToString(skuMap);
        }

        LambdaQueryWrapper<ProductSkuDO> skuWrapper = new LambdaQueryWrapper<>();
        skuWrapper.eq(ProductSkuDO::getProductId, param.getGoodsId()).eq(ProductSkuDO::getIsInvalid, 0).eq(StringUtils.isNotBlank(specJson), ProductSkuDO::getSpecJson, specJson);
        ProductSkuDO skuDO = productSkuMapper.selectOne(skuWrapper);
        if (Objects.isNull(skuDO)) {
            throw new BizException(ErrorConstants.SERVER_INTERNAL_ERROR, "规格不存在");
        }

        // 3. 校验附加项是否被该商品允许
        List<ShoppingCartParam.ProductAddition> additions = param.getAddition();
        if (CollectionUtils.isNotEmpty(additions)) {
            // 获取该商品允许的 addonOptionId 列表
            LambdaQueryWrapper<ProductBaseAddonRelationDO> relationWrapper = new LambdaQueryWrapper<>();
            relationWrapper.select(ProductBaseAddonRelationDO::getAddonOptionId).eq(ProductBaseAddonRelationDO::getProductId, param.getGoodsId()).eq(ProductBaseAddonRelationDO::getIsInvalid, 0);
            List<ProductBaseAddonRelationDO> allowedList = productBaseAddonRelationMapper.selectList(relationWrapper);
            Set<Long> allowedAddonOptionIds = allowedList.stream().map(ProductBaseAddonRelationDO::getAddonOptionId).collect(Collectors.toSet());

            for (ShoppingCartParam.ProductAddition add : additions) {
                if (!allowedAddonOptionIds.contains(add.getId())) {
                    throw new BizException(ErrorConstants.SERVER_INTERNAL_ERROR, "附加项 [" + add.getId() + "] 不适用于该商品");
                }
                // 可选：校验 addon_value 是否属于该 addon_option（需查 product_addon_value 表）
            }
        }

        // 4. 查询是否已有相同购物车条目（相同用户 + 商品 + SKU + 附加项组合）
        // 注意：附加项组合需精确匹配（顺序无关，内容一致）

        // 先查出所有当前用户的 cart 记录（同商品+SKU）
        LambdaQueryWrapper<ShoppingCartDO> cartQuery = new LambdaQueryWrapper<>();
        cartQuery.eq(ShoppingCartDO::getUserId, currentUserId).eq(ShoppingCartDO::getProductId, param.getGoodsId()).eq(ShoppingCartDO::getSkuId, skuDO.getId());
        List<ShoppingCartDO> candidateCarts = shoppingCartMapper.selectList(cartQuery);

        ShoppingCartDO targetCart = null;

        if (CollectionUtils.isNotEmpty(candidateCarts)) {
            // 获取每个 cart 对应的附加项列表 一个商品可能多个附加项
            for (ShoppingCartDO cart : candidateCarts) {
                LambdaQueryWrapper<ShoppingCartAddonRelationDO> addonQuery = new LambdaQueryWrapper<>();
                addonQuery.eq(ShoppingCartAddonRelationDO::getCartId, cart.getId());
                List<ShoppingCartAddonRelationDO> cartAddons = shoppingCartAddonRelationMapper.selectList(addonQuery);

                // 构建当前 cart 的 addon 映射：optionId -> valueId
                Map<Long, Long> cartAddonMap = cartAddons.stream().collect(Collectors.toMap(ShoppingCartAddonRelationDO::getAddonOptionId, ShoppingCartAddonRelationDO::getAddonValueId, (v1, v2) -> v1));

                // 构建用户传入的 addon 映射
                Map<Long, Long> inputAddonMap = additions == null ? Collections.emptyMap() : additions.stream().collect(Collectors.toMap(ShoppingCartParam.ProductAddition::getPid, ShoppingCartParam.ProductAddition::getId, (v1, v2) -> v1));

                // 比较是否完全一致（Map.equals 要求 key-value 完全相同，忽略顺序）
                if (cartAddonMap.equals(inputAddonMap)) {
                    targetCart = cart;
                    break;
                }
            }
        }

        Integer finalNumber = param.getNumber();

        // 该产品在购物车中存在 规格和附加项完全一致
        if (targetCart != null) {
            // 更新数量
            targetCart.setQuantity(targetCart.getQuantity() + finalNumber);
            shoppingCartMapper.updateById(targetCart);
            // 注意：不需要动关联表，因为附加项组合没变
        } else {
            // 新增购物车主记录
            ShoppingCartDO newCart = new ShoppingCartDO();
            newCart.setUserId(currentUserId);
            newCart.setProductId(param.getGoodsId());
            newCart.setSkuId(skuDO.getId());
            newCart.setShopId(productDO.getShopId());
            newCart.setCategoryId(productDO.getCategoryId());
            newCart.setProductName(productDO.getName());
            newCart.setSkuDesc(skuDO.getSpecText());
            newCart.setPicUrl(productDO.getPic());
            newCart.setUnitPrice(skuDO.getSalePrice());
            newCart.setQuantity(finalNumber);
            shoppingCartMapper.insert(newCart);

            // 新增附加项关联记录
            if (CollectionUtils.isNotEmpty(additions)) {
                List<ShoppingCartAddonRelationDO> relations = additions.stream().map(add -> {
                    ShoppingCartAddonRelationDO r = new ShoppingCartAddonRelationDO();
                    r.setCartId(newCart.getId());
                    r.setAddonOptionId(add.getPid());
                    r.setAddonValueId(add.getId());
                    return r;
                }).collect(Collectors.toList());
                shoppingCartAddonRelationMapper.insertBatch(relations);
            }
        }

        // 5. 构造返回 VO
        return info();
    }

    @Override
    public ShoppingCartVO select(ShoppingCartSelectParam select) {
        ShoppingCartDO shoppingCartDO = new ShoppingCartDO();
        shoppingCartDO.setId(select.getKey());
        shoppingCartDO.setIsSelected(select.getSelected() ? 1 : 0);
        shoppingCartMapper.updateById(shoppingCartDO);
        return info();
    }

    @Override
    public ShoppingCartVO modifyNumber(ShoppingCartUpdateNumParam param) {
        ShoppingCartDO shoppingCartDO = new ShoppingCartDO();
        shoppingCartDO.setId(param.getKey());
        shoppingCartDO.setQuantity(param.getNumber());
        shoppingCartMapper.updateById(shoppingCartDO);
        return info();
    }
}
